
package com.rivues.task;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskExecutor;

import com.rivues.core.RivuDataContext;
import com.rivues.module.platform.web.model.HistoryJobDetail;
import com.rivues.module.platform.web.model.JobDetail;
import com.rivues.module.platform.web.model.Reporter;
import com.rivues.module.platform.web.model.RivuSite;
import com.rivues.util.RivuTools;
import com.rivues.util.local.LocalTools;
import com.rivues.util.mail.MailSender;
import com.rivues.util.service.monitor.BusinessService;
import com.rivues.util.service.system.DataPersistenceService;
import com.rivues.util.tools.TaskHelper;

public class Task implements Runnable{
	private static Logger log = LoggerFactory.getLogger(Task.class) ;
	private JobDetail jobDetail ;
	
	public Task(JobDetail jobDetail){
		this.jobDetail = jobDetail ;
	}
	@SuppressWarnings("unchecked")
	@Override
	public void run() {
		Date startDate = new Date();
		int excute_result =  RivuDataContext.TaskResultType.SUCCESS.getType();
		try{
			/**
			 * 首先从  等待执行的队列中找到优先级最高的任务，然后将任务放入到  执行队列
			 */
			if(jobDetail!=null){
				RivuDataContext.getLocalRunningJob().put(jobDetail.getId(), jobDetail) ;
				
				Map<String , Object> values = new HashMap<String , Object>();
				values.put("job", jobDetail) ;
				String eventMsg = LocalTools.getMessage("I_JOBDETAIL_2000001" , values) ;//放在 重置任务状态之前，记录日志的时候能够看到任务的重置前的状态
				log.info(eventMsg) ;
				DataPersistenceService.persistence(BusinessService.createEventBean(eventMsg , jobDetail , "I_JOBDETAIL_2000001")) ;
				/**
				 * 开始启动执行线程
				 */
				jobDetail.setTaskfiretime(new Date());
				jobDetail.setTaskstatus(RivuDataContext.TaskStatusType.RUNNING.getType()) ;
				/**
				 * 更新任务状态
				 */
				RivuDataContext.getService().updateIObject(jobDetail) ;
				/**
				 * 任务开始执行
				 */
				if(true){
					int fetchNum = 1;
					while (jobDetail.isFetcher()) {
						jobDetail.setFetchNum(fetchNum++);
						if(jobDetail.getReport()==null){
							jobDetail.setReport(new Reporter());
						}
						long pages = jobDetail.getReport().getPages();
						new Fetcher(jobDetail).run();
						if(!jobDetail.getId().equals(jobDetail.getName())){//只有 CSV全表导出 才有 有 Name 和 ID相同的 任务
							RivuDataContext.getService().updateIObject(jobDetail);
						}
						if (jobDetail.getReport() == null || pages >= jobDetail.getReport().getPages()) {
							break;
						}
					}
				}

				/**
				 * 任务开始执行，执行完毕后 ，任务状态回执为  NORMAL
				 */
				if(jobDetail.getCronexp()!=null && jobDetail.getCronexp().length() > 0 && jobDetail.isPlantask() && !"operation".equals(jobDetail.getCrawltaskid())){
					jobDetail.setNextfiretime(TaskHelper.updateTaskNextFireTime(jobDetail));
				}else{
					/**
					 * 该任务是 后台任务，并且是 计划任务，如果是交互式任务，则需要在执行完毕后将该任务移除掉
					 */
				}
				jobDetail.setStartindex(0) ;	//将分页位置设置为从头开始，对数据采集有效，对RivuES增量采集无效
				jobDetail.setFetcher(true) ;
				jobDetail.setPause(false) ;
				jobDetail.setTaskstatus(RivuDataContext.TaskStatusType.NORMAL.getType()) ;
				jobDetail.setCrawltaskid(null);
//				jobDetail.setLastdate(new Date()) ;
				RivuDataContext.getService().updateIObject(jobDetail) ;
			}

		}catch (Exception e) {
			// TODO: handle exception
			excute_result = RivuDataContext.TaskResultType.FAILD.getType();
			e.printStackTrace();
			log.error("任务执行失败，任务名称："+jobDetail.getName()+"，异常信息："+e.getMessage());
			try {
				List<RivuSite> siteList = RivuDataContext.getService().findAllByCriteria(DetachedCriteria.forClass(RivuSite.class).add(Restrictions.eq("groupid",RivuDataContext.NotifiactionType.EMAIL.toString()))) ;
				if(siteList.size()>0){
					RivuSite emailSite = siteList.get(0) ;
					MailSender sender = new MailSender(emailSite.getSmtpserver(),emailSite.getMailfrom(),emailSite.getSmtpuser(), RivuTools.decryption(emailSite.getSmtppassword()));
					sender.send(jobDetail.getEmail(), jobDetail.getName()+"_执行失败", RivuTools.getExceptionMessage(e));
				}else{
					new Exception("邮件发送失败，未找到系统邮件配置导致邮件提醒未发送。");
				}
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				
			}
		}finally{
			if(!StringUtils.isBlank(jobDetail.getExceptionMsg())){
				excute_result = RivuDataContext.TaskResultType.FAILD.getType();
			}
			if(jobDetail!=null){
				/**
				 * 将任务从执行列表中删除
				 */
				if(jobDetail!=null){
					Map<String, Object> runningJobMap = RivuDataContext.getClusterInstance().get(RivuDataContext.DistributeEventEnum.RUNNINGJOB.toString()) ;
					runningJobMap.remove(jobDetail.getId()) ;
					/**
					 * 同时将任务从本地执行队列中移除
					 */
					if(RivuDataContext.getLocalRunningJob().get(jobDetail.getId())!=null){
						RivuDataContext.getLocalRunningJob().remove(jobDetail.getId()) ;
					}
				}
				/**
				 * 以下代码构建 任务历史信息
				 */
				HistoryJobDetail hisJobDetail = createHisJobDetail(jobDetail , startDate , new Date() , excute_result);
				/**
				 * 构建 任务历史
				 */
				StringBuffer strb = new StringBuffer();
				hisJobDetail.setStatus(strb.append("I_REPORT_100001").append(":").append(System.currentTimeMillis()).toString()) ;
				if(jobDetail.getReport()!=null && jobDetail.getReport().getStatus()!=null){
					if(jobDetail.getReport().getStatus().length()>255){
						hisJobDetail.setCatalog(jobDetail.getReport().getStatus().substring(0, 255));
					}else{
						hisJobDetail.setCatalog(jobDetail.getReport().getStatus());
					}
				}
				RivuDataContext.getService().saveIObject(hisJobDetail);
				if(jobDetail.getTasktype()!=null && jobDetail.getTasktype().equals(RivuDataContext.TaskTypeEnum.EXPORT.toString())){
					RivuDataContext.getService().deleteIObject(jobDetail) ;
				}
			}
		}
	}
	private HistoryJobDetail createHisJobDetail(JobDetail jobDetail , Date startTime , Date endTime , int resulttype){
		HistoryJobDetail historyJob = new HistoryJobDetail();
		try {
			org.apache.commons.beanutils.BeanUtils.copyProperties(historyJob, jobDetail);
			historyJob.setTaskfiretime(startTime) ;
			historyJob.setId(null) ;
			historyJob.setStarttime(startTime);
			historyJob.setEndtime(endTime);
			historyJob.setResulttype(resulttype) ;
			historyJob.setTaskid(jobDetail.getId()) ;
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return historyJob ;
	}
}
